package gwtspeechbubble.client;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;

public class SpeechBubble extends Composite {

    private FlowPanel bubble;
    private FlowPanel bubbleAndArrow;
    private Arrow arrow;
    private FlowPanel bubbleShadow;

    public SpeechBubble() {
        bubbleAndArrow = new FlowPanel();
        bubble = new FlowPanel();
        bubbleShadow = new FlowPanel();
        arrow = new Arrow();

        bubbleShadow.add(bubble);

        bubbleAndArrow.add(bubbleShadow);
        initWidget(bubbleAndArrow);
        bubbleAndArrow.add(arrow);
        configureStyle();
        DeferredCommand.addCommand(new Command() {
            public void execute() {
                resize();
            }
        });
    }

    private void configureStyle() {
        DOM.setStyleAttribute(getElement(), "position", "absolute");
        DOM.setStyleAttribute(getElement(), "float", "left");
        DOM.setStyleAttribute(getElement(), "backgroundColor", "transparent");
        DOM.setStyleAttribute(getElement(), "overflow", "hidden");

        DOM.setStyleAttribute(bubble.getElement(), "borderLeft", "2px solid black");
        DOM.setStyleAttribute(bubble.getElement(), "borderTop", "2px solid black");
        DOM.setStyleAttribute(bubble.getElement(), "borderRight", "1px solid black");
        DOM.setStyleAttribute(bubble.getElement(), "borderBottom", "1px solid black");
        DOM.setStyleAttribute(bubble.getElement(), "backgroundColor", "white");
        DOM.setStyleAttribute(bubble.getElement(), "position", "relative");
        DOM.setStyleAttribute(bubble.getElement(), "left", "-1px");
        DOM.setStyleAttribute(bubble.getElement(), "top", "-1px");

        DOM.setStyleAttribute(bubbleShadow.getElement(), "backgroundColor", "lightgray");
        DOM.setStyleAttribute(bubbleShadow.getElement(), "position", "relative");

        resize();
    }


    public SpeechBubble moveTo(int x, int y) {
        int xPos = resolveXPosition(x);
        int yPos = resolveYPosition(y);
        DOM.setStyleAttribute(getElement(), "left", xPos + "px");
        DOM.setStyleAttribute(getElement(), "top", yPos + "px");
        resize();
        return this;
    }


    private int resolveYPosition(int y) {
        return (getParent().getAbsoluteTop() + y) - bubbleAndArrow.getOffsetHeight();
    }

    private int resolveXPosition(int x) {
        return (getParent().getAbsoluteLeft() + x) - 18;
    }

    public SpeechBubble with(Widget widget) {
        bubble.add(widget);
        return resize();
    }

    private SpeechBubble resize() {
        arrow.realignArrow(getOffsetWidth());
        return this;
    }

    public SpeechBubble css(String bubbleCss) {
        bubble.setStyleName(bubbleCss);
        return this;
    }

}
